// 版权归Go作者所有。版权所有。
// 此源代码的使用受BSD样式的约束
// 可以在许可证文件中找到的许可证。

package ssa

import (
	"cmd/compile/internal/ir"
	"cmd/compile/internal/types"
	"fmt"
)

// ssa变量可以驻留的位置。
type Location interface {
	String() string // 要在程序集模板中使用的名称：AX，16（SP）。。。
}

// 寄存器是一种机器寄存器，如AX。
// 它们从0开始密集编号（对于每个体系结构）。
type Register struct {
	num    int32 // 密集编号
	objNum int16 // 来自cmd/internal/obj/$ARCH的寄存器编号
	gcNum  int16 // GC寄存器映射号（可包含指针的寄存器密集编号）
	name   string
}

func (r *Register) String() string {
	return r.name
}

// ObjNum从cmd/internal/obj/$ARCH返回寄存器号
// 与此寄存器相对应。
func (r *Register) ObjNum() int16 {
	return r.objNum
}

// GCNum返回运行时GC寄存器索引r，如果为-1
// 寄存器不能包含指针。
func (r *Register) GCNum() int16 {
	return r.gcNum
}

// LocalSlot是堆栈框架中的一个位置，用于标识和存储
// PPARAM、PPARAMOUT或PAUTO ONAME节点的一部分或全部。
// 它可以表示整个变量、更大堆栈槽的一部分，或者一个变量的一部分
// 已分解为多个堆栈插槽的变量。
// 例如，字符串可以具有以下配置：
// None
// 堆栈布局本地插槽
// None
// 已禁用优化。s位于堆栈上，并以其整体表示。
// [----s字符串----]{N:s，类型：字符串，关闭：0}
// None
// s未分解，但SSA单独对其部件进行操作，因此
// 指向单堆栈插槽的每个字段都有一个LocalSlot。
// [----s字符串----]{N:s，类型：*uint8，Off:0}，{N:s，类型：int，Off:8}
// None
// 木薯腐烂了。它的每个字段都在自己的堆栈插槽中，并且有自己的LocalSLot。
// [ptr*uint8][len int]{N:ptr，类型：*uint8，Off:0，SplitOf:parent，SplitOffset:0}，
// {N:len，Type:int，Off:0，SplitOf:parent，SplitOffset:8}
// 父项=&{N:s，类型：string}
type LocalSlot struct {
	N    *ir.Name    // 表示堆栈位置的ONAME*ir.Name。
	Type *types.Type // 插槽类型
	Off  int64       // N中插槽的偏移量

	SplitOf     *LocalSlot // slot是SplitOf的分解
	SplitOffset int64      // .. 在这个偏移量。
}

func (s LocalSlot) String() string {
	if s.Off == 0 {
		return fmt.Sprintf("%v[%v]", s.N, s.Type)
	}
	return fmt.Sprintf("%v+%d[%v]", s.N, s.Off, s.Type)
}

type LocPair [2]Location

func (t LocPair) String() string {
	n0, n1 := "nil", "nil"
	if t[0] != nil {
		n0 = t[0].String()
	}
	if t[1] != nil {
		n1 = t[1].String()
	}
	return fmt.Sprintf("<%s,%s>", n0, n1)
}

type LocResults []Location

func (t LocResults) String() string {
	s := "<"
	a := ""
	for _, r := range t {
		a += s
		s = ","
		a += r.String()
	}
	a += ">"
	return a
}

type Spill struct {
	Type   *types.Type
	Offset int64
	Reg    int16
}
